package com.gxs.tga.poc.rest;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gxs.tga.poc.domain.TgaSolution;
import com.gxs.tga.poc.domain.TgaSolutionTP;
import com.gxs.tga.poc.domain.TgaSolutionTR;
import com.gxs.tga.poc.domain.TgaWorksheet;
import com.gxs.tga.poc.domain.dto.TgaSolutionTPDto;
import com.gxs.tga.poc.domain.dto.TgaSolutionTRDto;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaSolution;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaSolutionTP;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaSolutionTR;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaWorksheet;
import com.gxs.tga.poc.domain.exceptions.InvalidClientRequest;
import com.gxs.tga.poc.rest.common.TgaRestResponse;
import com.gxs.tga.poc.service.TgaSolutionService;
import com.gxs.tga.poc.service.TgaSolutionTPService;
import com.gxs.tga.poc.service.TgaSolutionTRService;
import com.gxs.tga.poc.service.TgaWorksheetService;

@Component("tgaSolutionTRRestBean")
@Path("/solutions/{solutionId}/tradingRelationships")
public class TgaSolutionTRRestBean
{
	@Autowired
	private TgaSolutionTRService tgaSolutionTRService;
	
	@Autowired
	private TgaSolutionService tgaSolutionService;
	
	@Autowired
	private TgaSolutionTPService tgaSolutionTPService;
	
	@Autowired
	private TgaWorksheetService tgaWorksheetService;

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getAllTradingRelationshipsForSolution(@PathParam("solutionId") String solutionId)
	{

		try
		{
			TgaSolution solution = this.tgaSolutionService.findById(solutionId);
			
			if(solution == null)
			{
				throw new InvalidClientRequest("Error: No solution exists with the solution id: " + solutionId);
			}
			
			List<TgaSolutionTR> list = this.tgaSolutionTRService.findByTgaSolution(solution);
			List<TgaSolutionTRDto> returnList = new ArrayList<TgaSolutionTRDto>();
			
			for(TgaSolutionTR partner : list)
			{
				returnList.add(new TgaSolutionTRDto(partner));
			}
			return Response.status(Status.OK).entity(returnList).build();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			int statusCode = 500;
			TgaRestResponse response = new TgaRestResponse(statusCode, "Error Occurred: " + e.getMessage(), statusCode);
			return Response.status(statusCode).entity(response).build();
		}
	}

	@GET
	@Path("/{trRecordId}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getSingleTradingRelationshipFromSolution(@PathParam("trRecordId") String trRecordId)
	{
		TgaSolutionTR tgaSolutionTr = this.tgaSolutionTRService.findById(trRecordId);
		
		if (tgaSolutionTr == null)
		{
			int statusCode = 404;
			TgaRestResponse response = new TgaRestResponse(statusCode, "No record of type 'TgaSolutionTR' (Trading Relationship) exists with the id: " + trRecordId, statusCode);
			return Response.status(statusCode).entity(response).build();
		} else
		{
			TgaSolutionTRDto dto = new TgaSolutionTRDto(tgaSolutionTr);
			return Response.status(200).entity(dto).build();
		}

	}

	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public Response createOrUpdateTest(TgaSolutionTRDto dto, @PathParam("solutionId") String solutionId, @QueryParam("operation") String operation) throws InvalidClientRequest, DuplicateTgaWorksheet 
	{
		if(operation == null )
		{
			throw new InvalidClientRequest("Missing Query Parameter: 'operation' -- must be provided. Valid Values are: [create, update]");
		}
		else if(operation.equals("create") || operation.equals("update"))
		{
			// good
		}
		else
		{
			throw new InvalidClientRequest("Incorrect value for Query Parameter: 'operation' -- must be provided. Valid Values are: [create, update]");
		}
 
		if(operation.equals("update"))
		{
			throw new InvalidClientRequest("Work In Progress: Update operation is currently in development");
		}
		
		try
		{
			// First check that the specific solution exists
			
			if(dto.getSolutionId() != null )
			{
				throw new InvalidClientRequest("Error: solution id is taken from the path and should not be provided in the input JSON object");
			}
			
			if(dto.getTrRecordId() != null)
			{
				throw new InvalidClientRequest("Error: TRRecordId attribute is dynamically generated as primary key and should not be provided in the input data");
			}
			
			TgaSolution solution = this.tgaSolutionService.findById(solutionId);
			
			if(solution == null)
			{
				throw new InvalidClientRequest("Error: Given solution id: '" + solutionId + "' does not exist");
			}
			
			List<TgaSolutionTR> tpList = this.tgaSolutionTRService.findByCompIdAndAprfAndTgaSolution(dto.getCompId(), dto.getAprf(), solution);
			
			if(tpList != null && tpList.size() > 0)
			{
				throw new InvalidClientRequest("Error: A relationship with company id: " + dto.getCompId() + " and APRF " + dto.getAprf() + " combination already has been included in this solution as a trading relationship");
			}
			
			// Now verify that the company referenced in this relationship is already available in the TPs list (Datbase constraint will prevent this anyway - but 
			// proactive check with allow us to give a meaningful message
			List<TgaSolutionTP> listOfTps = this.tgaSolutionTPService.findByCompId(dto.getCompId());
			
			if(listOfTps == null || listOfTps.size() < 1)
			{
				throw new InvalidClientRequest("Error: The company referenced in this relationship (CompId=" + dto.getCompId() + ") does not exist as a trading partner in this solution. Please add the company to trading partners pool first");
			}
			
			// We only support two itineraries at this time: C-Translate and C-Deliver
			String itin = dto.getItineraryName();
			if(itin.equals("C-Translate") || itin.equals("C-Deliver"))
			{
				// Good
			}
			else
			{
				throw new InvalidClientRequest("Error: The only two itineraries supported in this POC are: C-Translate, and C-Deliver");
			}
			
			TgaSolutionTR tr = new TgaSolutionTR(dto, solution, true);
			
			this.tgaSolutionTRService.create(tr);

			
			//
			// Now add a service config if the service picked is translation
			if(itin.equals("C-Translate"))
			{
				TgaWorksheet worksheet = new TgaWorksheet();
				worksheet.setSheetInstanceId(UUID.randomUUID().toString());
				worksheet.setParentWorksheetId(tr.getTrRecordId());
				worksheet.setSheetDataBlob(null);
				worksheet.setSheetId("translateConfig");
				worksheet.setSheetName("Translation Config");
				worksheet.setShellId(TgaWorksheet.WORKSHEET_SHELL_ID_SVCS);
				worksheet.setTgaSolution(solution);
				
				this.tgaWorksheetService.create(worksheet);
			}
			
			
			int statusCode  = Response.Status.CREATED.getStatusCode();
			TgaSolutionTRDto dtoToReturn = new TgaSolutionTRDto(tr);
			
			
			TgaRestResponse response = new TgaRestResponse(statusCode, "A trading relationship has been created with the trRecordId: " + tr.getTrRecordId());
			response.setTargetResource(dtoToReturn);
			response.setTargetResourceRefId(tr.getTrRecordId());
			response.setTargetResourcePKAttributeName("trRecordId");
			
			return Response.status(statusCode).entity(response).build();
		}
		catch(DuplicateTgaSolutionTR dte)
		{
			int statusCode  = Response.Status.CONFLICT.getStatusCode();
			TgaRestResponse response = new TgaRestResponse(statusCode, "Error: Trading Relationship with record id: " + dto.getTrRecordId() +  ", and company id: " +  dto.getCompId() +" already exists" , statusCode);
			return Response.status(statusCode).entity(response).build();

		}
		
		
	}
 
}
